package array

import "fmt"

type FlArray struct {
	data []interface{}
	size int
	capacity int
}

const (
	defaultCapacity = 1<<4

)

type FunctionOption func(opt *FlArray)

func WithCapacity(capacity int ) FunctionOption {
	return func(opt *FlArray) {
		opt.capacity = capacity
	}
}

func WithSize(size int ) FunctionOption {
	return func(opt *FlArray) {
		opt.size = size
	}
}

func New(options ...FunctionOption) * FlArray{
	a := &FlArray{capacity: defaultCapacity}
	for _, option := range options {
		option(a)
	}
	a.data = make([]interface{},a.size,a.capacity)
	return a
}

func (f *FlArray) Size() int {
	return f.size
}

func (f *FlArray) Capacity() int {
	return f.capacity
}

func (f *FlArray) IsEmpty() bool {
	return f.size == 0
}

func (f *FlArray) Add(idx int,v interface{})  {
	if idx<0 || idx>f.size{
		panic("索引越界")
	}

	if f.size ==f.capacity {
		f.capacity = f.size<<1
		newData := make([]interface{},f.capacity)
		copy(newData,f.data)
		f.data = newData
	}

	for i := f.size-1; i >= idx; i-- {
		f.data[i+1] = f.data[i]
	}
	f.data[idx] = v
	f.size++
}

func (f *FlArray) AddLast(v interface{})  {
	f.Add(f.size,v)
}
func (f *FlArray) Println()  {
	data := make([]interface{},0,f.size)
	f.Each(func(v interface{}) {
		data = append(data,v)
	})
	fmt.Println(data)
}

func (f *FlArray) AddFirst(v interface{})  {
	f.Add(0,v)
}

func (f *FlArray) Delete(idx int)(elem interface{}) {
	if idx<0||idx>f.size-1 {
		panic("索引越界")
	}
	elem = f.data[idx]
	for i := idx; i < f.size; i++ {
		f.data[i] = f.data[i+1]
	}
	f.size--
	if f.size < f.capacity>>2 {
		f.capacity = f.capacity>>1
		newData := make([]interface{},f.capacity)
		copy(newData,f.data)
		f.data = newData
	}
	return
}

func (f *FlArray) DeleteFirst() (elem interface{}) {
	return f.Delete(0)
}

func (f *FlArray) DeleteLast() (elem interface{}) {
	return f.Delete(f.size-1)
}

func (f *FlArray) Update(idx int, v interface{})  {
	if idx<0||idx>f.size {
		panic("索引越界")
	}
	f.data[idx] = v
}

func (f *FlArray) Find(idx int) interface{} {
	if idx<0||idx>f.size {
		panic("索引越界")
	}
	return f.data[idx]
}

func (f *FlArray) FindLast() interface{} {
	return f.Find(f.size-1)
}

func (f *FlArray) FindFirst() interface{} {
	return f.Find(0)
}

func (f *FlArray) FindByElem(v interface{}) int {
	for i := 0; i < f.size; i++ {
		if f.data[i]==v {
			return i
		}
	}
	return -1
}

func (f *FlArray) Each(cb func(v interface{}))  {
	for i := 0; i < f.size; i++ {
		cb(f.data[i])
	}
}

